#ifndef UTILS_AUTO_CLEANUP_HPP
#define UTILS_AUTO_CLEANUP_HPP


namespace utils
{

// TODO: Document
class auto_cleanup
{
	auto_cleanup( const auto_cleanup& );
	auto_cleanup& operator=( const auto_cleanup& );

	class abstract_destroyer
	{
	public:
		virtual void destroy() = 0;
		virtual ~abstract_destroyer() {}
	};

	template< class D>
	class destroyer: public abstract_destroyer
	{
	public:
		destroyer( const D& d)
			: d_( d)
		{
		}

		virtual void destroy() { d_(); }

	private:
		D d_;
	};

public:
	template< class I, class D>
	auto_cleanup( const I& i, const D& d)
		: d_( new destroyer< D>( d))
	{
		i();
	}

	~auto_cleanup() throw()
	{
		d_->destroy();
		delete d_;
	}

private:
	abstract_destroyer* d_;
};

} // namespace utils

#endif // UTILS_AUTO_CLEANUP_HPP
